package com.fenghuajueli.lib_pictureselect.utils;

import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.MediaStore;
import android.text.TextUtils;
import android.util.Log;

import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;

import com.blankj.utilcode.util.LogUtils;
import com.fenghuajueli.lib_pictureselect.mimetype.MimeUtils;

import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import okio.BufferedSink;
import okio.BufferedSource;
import okio.Okio;

/**
 * 复制视频到公共目录是，只能使用MediaStore.Video.Media.EXTERNAL_CONTENT_URI来创建一个uri。
 */
public class FileQUtils {

    /**
     * 将文件存放到公共下载目录
     *
     * @param context   上下文
     * @param fileName  文件的名字
     * @param extension 文件的类型
     * @return uri  拿到uri可以得到outputstream 向里面写入数据
     */
    public static Uri insertFileIntoMediaStore(Context context, String fileName, String extension, String folderName) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
            return null;
        }
        ContentResolver resolver = context.getContentResolver();
        //设置文件参数到ContentValues中
        ContentValues values = new ContentValues();
        //设置文件名
        values.put(MediaStore.Files.FileColumns.DISPLAY_NAME, fileName);
        //设置文件类型
        values.put(MediaStore.Files.FileColumns.MIME_TYPE, MimeUtils.guessMimeTypeFromExtension(extension));
        //注意RELATIVE_PATH需要targetVersion=29
        //故该方法只可在Android10的手机上执行
        values.put(MediaStore.Downloads.RELATIVE_PATH, Environment.DIRECTORY_DOCUMENTS + File.separator + folderName);
        Uri uri = resolver.insert(MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL), values);
        //EXTERNAL_CONTENT_URI代表外部存储器
//        Uri external = MediaStore.Downloads.EXTERNAL_CONTENT_URI;
//        //insertUri表示文件保存的uri路径
//
//        Uri insertUri = resolver.insert(external, values);
        return uri;
    }

    public static Uri queryFileIntoMediaStore(Context context, String fileName, String extension, String folderName) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
            return null;
        }
        ContentResolver resolver = context.getContentResolver();
        //设置文件参数到ContentValues中
        ContentValues values = new ContentValues();
        //设置文件名
        values.put(MediaStore.Files.FileColumns.DISPLAY_NAME, fileName);
        //设置文件类型
        values.put(MediaStore.Files.FileColumns.MIME_TYPE, MimeUtils.guessMimeTypeFromExtension(extension));
        //注意RELATIVE_PATH需要targetVersion=29
        //故该方法只可在Android10的手机上执行
        values.put(MediaStore.Downloads.RELATIVE_PATH, Environment.DIRECTORY_DOCUMENTS + File.separator + folderName);
        Uri uri = resolver.insert(MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL), values);
        //EXTERNAL_CONTENT_URI代表外部存储器
//        Uri external = MediaStore.Downloads.EXTERNAL_CONTENT_URI;
//        //insertUri表示文件保存的uri路径
//
//        Uri insertUri = resolver.insert(external, values);
        return uri;
    }


    /**
     * 根据文件的在公共目录的相对路径，去获取文件的uri
     *
     * @param context
     * @param filePath 文件在公共目录的相对路径  例如  Documents/wordFolder/1.docx
     * @return
     */
    public static Uri getUriFromPath(Context context, String filePath) {
        if (TextUtils.isEmpty(filePath)) {
            return null;
        }
        String fileName = filePath.substring(filePath.lastIndexOf("/") + 1);
        String basePath = filePath.substring(0, filePath.lastIndexOf("/") + 1);
        LogUtils.d("文件的名字：" + fileName, basePath);
        if (TextUtils.isEmpty(fileName)) {
            return null;
        }
        String queryPathKey = MediaStore.Files.FileColumns.RELATIVE_PATH;
        String selection = queryPathKey + "=? and " + MediaStore.Files.FileColumns.DISPLAY_NAME + "=?";
        Cursor cursor = context.getContentResolver().query(MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL),
                new String[]{MediaStore.Files.FileColumns._ID, queryPathKey, MediaStore.Files.FileColumns.DISPLAY_NAME},
                selection,
                new String[]{basePath, fileName},
                null);
        if (cursor != null && cursor.moveToNext()) {
            int id = cursor.getInt(cursor.getColumnIndex(MediaStore.Images.Media._ID));
            LogUtils.d("两个值：", MediaStore.Images.Media.EXTERNAL_CONTENT_URI, MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL));
            Uri contentUri = ContentUris.withAppendedId(MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL), id);
            cursor.close();
            return contentUri;
        } else {
            return null;
        }
    }

    /**
     * 拷贝私有目录的文件到共有目录
     *
     * @param context     上下文
     * @param mimeType    文件的类型
     * @param folderName  文件存放在公共目录下的文件夹的名字
     * @param orgFilePath 私有文件的地址 ，自己包下面的文件
     * @param displayName 存放的名字
     */
    @RequiresApi(api = Build.VERSION_CODES.Q)
    public static void copyPrivateToDownload(Context context, String mimeType, String folderName, String orgFilePath, String displayName) {
        ContentValues values = new ContentValues();
        values.put(MediaStore.Files.FileColumns.DISPLAY_NAME, displayName);
        values.put(MediaStore.Files.FileColumns.MIME_TYPE, mimeType);//MediaStore对应类型名
        values.put(MediaStore.Files.FileColumns.TITLE, displayName);
        values.put(MediaStore.Downloads.RELATIVE_PATH, folderName);//公共目录下目录名例如 "Download/Test"
        Uri external = MediaStore.Downloads.EXTERNAL_CONTENT_URI;//内部存储的Download路径
        ContentResolver resolver = context.getContentResolver();
        Uri insertUri = resolver.insert(external, values);//使用ContentResolver创建需要操作的文件
        InputStream ist = null;
        OutputStream ost = null;
        try {
            ist = new FileInputStream(new File(orgFilePath));
            if (insertUri != null) {
                ost = resolver.openOutputStream(insertUri);
            }
            if (ost != null) {
                byte[] buffer = new byte[4096];
                int byteCount = 0;
                while ((byteCount = ist.read(buffer)) != -1) {  // 循环从输入流读取 buffer字节
                    ost.write(buffer, 0, byteCount);        // 将读取的输入流写入到输出流
                }
                // write what you want
            }
        } catch (IOException e) {

        } finally {
            try {
                if (ist != null) {
                    ist.close();
                }
                if (ost != null) {
                    ost.close();
                }
            } catch (IOException e) {

            }
        }
    }


    /**
     * 拷贝私有目录的文件到DCIM/Camera目录下
     *
     * @param context     上下文
     * @param mimeType    文件的类型
     * @param orgFilePath 私有文件的地址 ，自己包下面的文件
     * @param displayName 存放的名字
     */
    @RequiresApi(api = Build.VERSION_CODES.Q)
    public static Uri copyVideoPrivateToDCIM(Context context, String mimeType, String orgFilePath, String displayName) {
        ContentValues values = new ContentValues();
        values.put(MediaStore.Files.FileColumns.DISPLAY_NAME, displayName);
        values.put(MediaStore.Files.FileColumns.MIME_TYPE, mimeType);//MediaStore对应类型名
        values.put(MediaStore.Files.FileColumns.TITLE, displayName);
        values.put(MediaStore.Downloads.RELATIVE_PATH, Environment.DIRECTORY_DCIM + File.separator + "Camera");//公共目录下目录名例如 "Download/Test"
        ContentResolver resolver = context.getContentResolver();
        Uri insertUri = resolver.insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, values);
        InputStream ist = null;
        OutputStream ost = null;
        try {
            ist = new FileInputStream(new File(orgFilePath));
            if (insertUri != null) {
                ost = resolver.openOutputStream(insertUri);
            }
            if (ost != null) {
                byte[] buffer = new byte[4096];
                int byteCount = 0;
                while ((byteCount = ist.read(buffer)) != -1) {  // 循环从输入流读取 buffer字节
                    ost.write(buffer, 0, byteCount);        // 将读取的输入流写入到输出流
                }
            }

            return insertUri;
        } catch (IOException e) {
            LogUtils.d("文件移动失败：" + e.toString());
            return null;
        } finally {
            try {
                if (ist != null) {
                    ist.close();
                }
                if (ost != null) {
                    ost.close();
                }
            } catch (IOException e) {
                return null;
            }
        }
    }



    /**
     * 拷贝私有目录的文件到DCIM/Camera目录下
     *
     * @param context     上下文
     * @param mimeType    文件的类型
     * @param orgFilePath 私有文件的地址 ，自己包下面的文件
     * @param displayName 存放的名字
     */
    @RequiresApi(api = Build.VERSION_CODES.Q)
    public static boolean copyVideoPrivateToDCIM2(Context context, String mimeType, String orgFilePath, String displayName) {
        ContentValues values = new ContentValues();
        values.put(MediaStore.Files.FileColumns.DISPLAY_NAME, displayName);
        values.put(MediaStore.Files.FileColumns.MIME_TYPE, mimeType);//MediaStore对应类型名
        values.put(MediaStore.Files.FileColumns.TITLE, displayName);
        values.put(MediaStore.Downloads.RELATIVE_PATH, Environment.DIRECTORY_DCIM + File.separator + "Camera");//公共目录下目录名例如 "Download/Test"
        ContentResolver resolver = context.getContentResolver();
        Uri insertUri = resolver.insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, values);
        InputStream ist = null;
        OutputStream ost = null;
        try {
            ist = new FileInputStream(new File(orgFilePath));
            if (insertUri != null) {
                ost = resolver.openOutputStream(insertUri);
            }
            if (ost != null) {
                byte[] buffer = new byte[4096];
                int byteCount = 0;
                while ((byteCount = ist.read(buffer)) != -1) {  // 循环从输入流读取 buffer字节
                    ost.write(buffer, 0, byteCount);        // 将读取的输入流写入到输出流
                }
            }

            return true;
        } catch (IOException e) {
            LogUtils.d("文件移动失败：" + e.toString());
            return false;
        } finally {
            try {
                if (ist != null) {
                    ist.close();
                }
                if (ost != null) {
                    ost.close();
                }
            } catch (IOException e) {
                return false;
            }
        }
    }

    /**
     * 拷贝私有目录的文件到DCIM/Camera目录下
     *
     * @param context     上下文
     * @param mimeType    文件的类型
     * @param orgFilePath 私有文件的地址 ，自己包下面的文件
     * @param displayName 存放的名字
     */
    @RequiresApi(api = Build.VERSION_CODES.Q)
    public static boolean copyImagePrivateToDCIM(Context context, String mimeType, String orgFilePath, String displayName) {
        ContentValues values = new ContentValues();
        values.put(MediaStore.Images.ImageColumns.DISPLAY_NAME, displayName);
        values.put(MediaStore.Images.ImageColumns.MIME_TYPE, mimeType);//MediaStore对应类型名
        values.put(MediaStore.Images.ImageColumns.TITLE, displayName);
        values.put(MediaStore.Downloads.RELATIVE_PATH, Environment.DIRECTORY_DCIM + File.separator + "Camera");
        ContentResolver resolver = context.getContentResolver();
        Uri insertUri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
        InputStream ist = null;
        OutputStream ost = null;
        try {
            ist = new FileInputStream(new File(orgFilePath));
            if (insertUri != null) {
                ost = resolver.openOutputStream(insertUri);
            }
            if (ost != null) {
                byte[] buffer = new byte[4096];
                int byteCount = 0;
                while ((byteCount = ist.read(buffer)) != -1) {  // 循环从输入流读取 buffer字节
                    ost.write(buffer, 0, byteCount);        // 将读取的输入流写入到输出流
                }
            }
            return true;
        } catch (IOException e) {
            LogUtils.d("文件移动失败：" + e.toString());
            return false;
        } finally {
            try {
                if (ist != null) {
                    ist.close();
                }
                if (ost != null) {
                    ost.close();
                }
            } catch (IOException e) {
                return false;
            }
        }
    }

    public static String moveFileToPrivate(Context context, Uri uri, String moveFolder) {
        InputStream originInputStream = null;
        BufferedSource inBuffer = null;
        ContentResolver contentResolver = context.getContentResolver();
        try {
            if (contentResolver != null) {
                String fileName = String.valueOf(System.currentTimeMillis());
                String mimeType = "";
                Cursor cursor = contentResolver.query(uri, null, null, null, null);
                if (cursor != null && cursor.getCount() > 0) {
                    cursor.moveToFirst();
                    fileName = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DISPLAY_NAME));
                    mimeType = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.MIME_TYPE));
                    cursor.close();
                } else {
                    LogUtils.d("此文件不存在：" + fileName);
                    return "";
                }
                Log.d("moveFileToPrivate：", "文件的名字：" + fileName + "---->mimeType:" + MimeUtils.guessExtensionFromMimeType(mimeType));
                //开始操作 Uri 到 File
                originInputStream = contentResolver.openInputStream(uri);
                //openAssetFile(uri, "r", null).createInputStream();
                if (originInputStream == null) {
                    return "";
                }
                String path = moveFolder + fileName;
                File file = new File(path);
                if (!file.exists()) {
                    file.createNewFile();
                }
                inBuffer = Okio.buffer(Okio.source(originInputStream));
                bufferCopy(inBuffer, file);
                Log.d("moveFileToPrivate:", "移动文件成功：" + path);
                return path;
            } else {
                return "";
            }
        } catch (IOException e) {
            LogUtils.e("文件移动异常：" + e.toString());
            return "";
        } finally {
            //这里关闭IO流
            try {
                close(inBuffer);
                if (originInputStream != null) {
                    originInputStream.close();
                }
            } catch (Exception e) {
                Log.e("", "流关闭异常：" + e.toString());
            }
        }
    }

    /**
     * 拷贝文件
     *
     * @param outFile
     * @return
     */
    public static boolean bufferCopy(BufferedSource inBuffer, File outFile) {
        BufferedSink outBuffer = null;
        try {
            outBuffer = Okio.buffer(Okio.sink(outFile));
            outBuffer.writeAll(inBuffer);
            outBuffer.flush();
            return true;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            close(inBuffer);
            close(outBuffer);
        }
        return false;
    }

    @SuppressWarnings("ConstantConditions")
    public static void close(@Nullable Closeable c) {
        // java.lang.IncompatibleClassChangeError: interface not implemented
        if (c != null && c instanceof Closeable) {
            try {
                c.close();
            } catch (Exception e) {
                // silence
            }
        }
    }


    /**
     * 复制文件至AndroidQ手机相册目录
     *
     * @param context
     * @param inFile
     * @param outUri
     */
    public static boolean copyPathToDCIM(Context context, File inFile, Uri outUri) {
        try {
            OutputStream fileOutputStream = context.getContentResolver().openOutputStream(outUri);
            return bufferCopy(inFile, fileOutputStream);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 拷贝文件
     *
     * @param inFile
     * @param outPutStream
     * @return
     */
    public static boolean bufferCopy(File inFile, OutputStream outPutStream) {
        BufferedSource inBuffer = null;
        BufferedSink outBuffer = null;
        try {
            inBuffer = Okio.buffer(Okio.source(inFile));
            outBuffer = Okio.buffer(Okio.sink(outPutStream));
            outBuffer.writeAll(inBuffer);
            outBuffer.flush();
            return true;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            close(inBuffer);
            close(outPutStream);
            close(outBuffer);
        }
        return false;
    }

    /**
     * 获取文件的真实路径，如果要通过真实路径来访问文件，请保证targetSdkVersion<29
     *
     * @param context
     * @param uri
     * @return 文件的真实路径
     */
    public static String getRealFilePath(final Context context, final Uri uri) {
        if (null == uri) return null;
        final String scheme = uri.getScheme();
        String data = null;
        if (scheme == null)
            data = uri.getPath();
        else if (ContentResolver.SCHEME_FILE.equals(scheme)) {
            data = uri.getPath();
        } else if (ContentResolver.SCHEME_CONTENT.equals(scheme)) {
            Cursor cursor = context.getContentResolver().query(uri, new String[]{MediaStore.Images.ImageColumns.DATA}, null, null, null);
            if (null != cursor) {
                if (cursor.moveToFirst()) {
                    int index = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
                    if (index > -1) {
                        data = cursor.getString(index);
                    }
                }
                cursor.close();
            }
        }
        return data;
    }


    /**
     * 读写普通文件，例如txt
     *
     * @param context
     * @param fileName just file name, not include path
     * @param subDir   sub direction name, not absolute path
     */
    public static void saveTxt2Public(Context context, String fileName, String content, String subDir) {
        String subDirection;
        if (!TextUtils.isEmpty(subDir)) {
            if (subDir.endsWith("/")) {
                subDirection = subDir.substring(0, subDir.length() - 1);
            } else {
                subDirection = subDir;
            }
        } else {
            subDirection = "Documents";
        }

        Cursor cursor = searchTxtFromPublic(context, subDir, fileName);
        if (cursor != null && cursor.moveToFirst()) {
            try {
                int id = cursor.getInt(cursor.getColumnIndex(MediaStore.Files.FileColumns._ID));
                Uri uri = Uri.withAppendedPath(MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL), "" + id);
                //Uri contentUri = ContentUris.withAppendedId(MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL), id);
                if (uri != null) {
                    OutputStream outputStream = context.getContentResolver().openOutputStream(uri);
                    if (outputStream != null) {
                        outputStream.write(content.getBytes());
                        outputStream.flush();
                        outputStream.close();
                    }
                }
                return;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        try {
            ContentValues contentValues = new ContentValues();
            contentValues.put(MediaStore.Files.FileColumns.DISPLAY_NAME, fileName);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                contentValues.put(MediaStore.Files.FileColumns.RELATIVE_PATH, subDirection);
            } else {
                //普通存储

            }
            //设置文件类型
            contentValues.put(MediaStore.Files.FileColumns.MEDIA_TYPE, MediaStore.Files.FileColumns.MEDIA_TYPE_NONE);
            Uri uri = context.getContentResolver().insert(MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL), contentValues);
            if (uri != null) {
                OutputStream outputStream = context.getContentResolver().openOutputStream(uri);
                if (outputStream != null) {
                    outputStream.write(content.getBytes());
                    outputStream.flush();
                    outputStream.close();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 安卓10获取文件的cursor
     *
     * @param context
     * @param filePath 不是文件的全路径，只是相对路径  Documents/wordFolder/xxxx.docx
     * @return
     */
    public static Cursor searchTxtFromPublic(Context context, String filePath, String fileName) {
        if (TextUtils.isEmpty(fileName)) {
            Log.e("searchTxtFromPublic", "searchTxtFromPublic: fileName is null");
            return null;
        }
        if (!filePath.endsWith("/")) {
            filePath = filePath + "/";
        }

        String queryPathKey = MediaStore.Files.FileColumns.RELATIVE_PATH;
        String selection = queryPathKey + "=? and " + MediaStore.Files.FileColumns.DISPLAY_NAME + "=?";
        Cursor cursor = context.getContentResolver().query(MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL),
                new String[]{MediaStore.Files.FileColumns._ID, queryPathKey, MediaStore.Files.FileColumns.DISPLAY_NAME},
                selection,
                new String[]{filePath, fileName},
                null);

        return cursor;
    }

    /**
     * 安卓10判断文件是否存在
     *
     * @param context
     * @param filePath
     * @param fileName
     * @return
     */
    public static boolean checkQFileIsExists(Context context, String filePath, String fileName) {
        if (TextUtils.isEmpty(fileName)) {
            return false;
        }
        if (!filePath.endsWith("/")) {
            filePath = filePath + "/";
        }
        String queryPathKey = MediaStore.Files.FileColumns.RELATIVE_PATH;
        String selection = queryPathKey + "=? and " + MediaStore.Files.FileColumns.DISPLAY_NAME + "=?";
        Cursor cursor = context.getContentResolver().query(MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL),
                new String[]{MediaStore.Files.FileColumns._ID, queryPathKey, MediaStore.Files.FileColumns.DISPLAY_NAME},
                selection,
                new String[]{filePath, fileName},
                null);
        if (cursor != null) {
            if (cursor.moveToNext()) {
                cursor.close();
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
    }

}